#ifndef _CELL_H_
#define _CELL_H_

#include <iostream>
#include <vector>
#include <set>
#include <hash_set>
#include <boost\optional\optional.hpp>
#include <exception>
#include "segment.h"
#include "point.h"
#include "manhatline.h"


#ifdef linux
namespace stdext = __gnu_cxx;
#endif

struct cell_t
{
    cell_t();
    cell_t(point_t const & center);
    point_t const & center() const;
    bool center_in() const;
    void center_in(bool flag);

    bool empty() const;
    void clear();
    size_t size() const;
    segment_t const & operator[] (size_t idx) const;
    segment_t & operator [](size_t idx);

    boost::optional<segment_t const &> min_segment(manhattan_line_t const & m_line, manhattan_part_t part) const;

    //static segment_t const default_seg;

    friend struct inserter;
    friend struct inserter_without_intersections;

    friend bool operator== (cell_t const & left, cell_t const & right);
    friend std::ostream & operator<< (std::ostream & out, cell_t const & cell);
    friend std::istream & operator>> (std::istream & in, cell_t & cell);
private:
    point_t center_;
    bool center_in_;
protected:
    std::vector<segment_t> segments_;
};

bool operator!= (cell_t const & left, cell_t const & right);

struct inserter
{
    void operator() (cell_t & cell, segment_t const & segment) const;
};

struct inserter_without_intersections
{
    void operator() (cell_t & cell, segment_t const & segment) const;
};

struct self_intersection_exc : std::exception
{
    self_intersection_exc() throw();
    char const * what() const throw();
    ~self_intersection_exc() throw();
private:
    std::string exc_;
};

#endif
